package com.fany.views.controls;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.TextView;

public class ListViewAdapter extends BaseAdapter
{
	private int _selectedIndex = -1;
	private int[] _to;
	private String[] _from;
	private ViewBinder _viewBinder;

	private List<? extends Map<String, ?>> _data;

	private int _resource;
	private LayoutInflater _inflater;

	public ListViewAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
	{
		_data = data;
		_resource = resource;
		_from = from;
		_to = to;
		_inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

	@Override
	public int getCount()
	{
		return _data.size();
	}

	@Override
	public Object getItem(int position)
	{
		return _data.get(position);
	}

	@Override
	public long getItemId(int position)
	{
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent)
	{
		View view = createViewFromResource(position, convertView, parent, _resource);
		if ((view != null) && (_selectedIndex == position))
		{
			view.setBackgroundColor(0x8800CCFF);
		}
		else
		{
			view.setBackgroundColor(Color.TRANSPARENT);
		}
		return view;
	}

	private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource)
	{
		View view;
		if (convertView == null)
		{
			view = _inflater.inflate(resource, parent, false);
		}
		else
		{
			view = convertView;
		}

		bindView(position, view);

		return view;
	}

	private void bindView(int position, View view)
	{
		final Map<String, ?> dataSet = _data.get(position);
		if (dataSet == null)
		{
			return;
		}

		final int count = _to.length;
		for (int i = 0; i < count; i++)
		{
			final View v = view.findViewById(_to[i]);
			if (v != null)
			{
				final Object data = dataSet.get(_from[i]);
				String text = data == null ? "" : data.toString();
				if (text == null)
				{
					text = "";
				}

				boolean bound = false;
				if (_viewBinder != null)
				{
					bound = _viewBinder.setViewValue(v, data, text);
				}

				if (!bound)
				{
					if (v instanceof Checkable)
					{
						if (data instanceof Boolean)
						{
							((Checkable) v).setChecked((Boolean) data);
						}
						else if (v instanceof TextView)
						{
							setViewText((TextView) v, text);
						}
						else
						{
							throw new IllegalStateException(v.getClass().getName()
									+ " should be bound to a Boolean, not a "
									+ (data == null ? "<unknown type>" : data.getClass()));
						}
					}
					else if (v instanceof TextView)
					{
						setViewText((TextView) v, text);
					}
					else if (v instanceof ImageView)
					{
						if (data instanceof Integer)
						{
							setViewImage((ImageView) v, (Integer) data);
						}
						else
						{
							setViewImage((ImageView) v, text);
						}
					}
					else
					{
						throw new IllegalStateException(v.getClass().getName() + " is not a "
								+ " view that can be bounds by this SimpleAdapter");
					}
				}
			}
		}
	}

	public void setViewText(TextView v, String text)
	{
		v.setText(text);
	}

	public void setViewImage(ImageView v, String value)
	{
		try
		{
			v.setImageResource(Integer.parseInt(value));
		}
		catch (NumberFormatException nfe)
		{
			v.setImageURI(Uri.parse(value));
		}
	}

	public void setViewImage(ImageView v, int value)
	{
		v.setImageResource(value);
	}

	public void setViewBinder(ViewBinder viewBinder)
	{
		_viewBinder = viewBinder;
	}

	public void setSelectedIndex(int selectedIndex)
	{
		this._selectedIndex = selectedIndex;
	}
	
	public int getSelectedIndex()
	{
		return this._selectedIndex;
	}

	public static interface ViewBinder
	{
		boolean setViewValue(View view, Object data, String textRepresentation);
	}
}
